package contents

import (
	"fmt"
	"github.com/pkg/errors"
	"yizhuoyan/go-study/pdfgo/raw/data"
	"yizhuoyan/go-study/pdfgo/raw/objects/basicobject"
	"yizhuoyan/go-study/pdfgo/raw/objects/indirectobject"
	"yizhuoyan/go-study/pdfgo/raw/objects/streamobject"
)

var pageTypeValueString = "/Page"

type Page struct {
	ObjectNumber        int
	ObjectVersionNumber int
	dic                 *basicobject.Dictionary
	locator             indirectobject.Locator
	Parent              *Pages                          `#:"(Required; ) "`
	MediaBox            *data.Rectangle                 `#:"(Required; inheritable) "`
	Resources           *Resources                      `#:"(Required; inheritable) "`
	contents            *PageContentStreams             `#:"(Optional; PDF 1.3) "`
	CropBox             *data.Rectangle                 `#:"(Optional; inheritable) "`
	BleedBox            *data.Rectangle                 `#:"(Optional; PDF 1.3) "`
	TrimBox             *data.Rectangle                 `#:"(Optional; PDF 1.3) "`
	ArtBox              *data.Rectangle                 `#:"(Optional; PDF 1.3) "`
	BoxColorInfo        *basicobject.Dictionary         `#:"(Optional; PDF 1.3) "`
	rotate              int                             `#:"Optional; inheritable"`
	Group               *basicobject.Dictionary         `#:"Optional; inheritable"`
	Thumb               *streamobject.BytesStreamObject `#:"Optional; inheritable"`
}

func (this *Page) GetObjectNumberAndVersion() string {
	return fmt.Sprintf("%v %v", this.ObjectNumber, this.ObjectVersionNumber)
}
func (this *Page) ParseFrom(parent *Pages, obj *indirectobject.IndirectObject) error {
	dic := obj.MustGetDictionary()
	if !dic.HasKeyAndNameValue("/Type", pageTypeValueString) {
		return errors.Errorf("非%s /Type", pageTypeValueString)
	}
	if !dic.HasKey("/Parent") {
		return errors.New("必须包含/Parent")
	}
	this.Parent = parent
	this.locator = parent.locator
	this.dic = dic
	this.ObjectNumber = obj.ObjectNumber
	this.ObjectVersionNumber = obj.ObjectVersionNumber
	if err := this.parseRequiredMediaBox(); err != nil {
		return errors.Wrapf(err, "parseRequiredMediaBox")
	}
	if err := this.parseRequiredResources(); err != nil {
		return errors.Wrapf(err, "parseRequiredResources")
	}

	return nil
}
func (this *Page) GetContents() (*PageContentStreams, error) {
	rst := this.dic.MustGetIndirectObjectReference("/Contents")
	if rst == nil {
		return nil, nil
	}
	this.contents = new(PageContentStreams)
	if err := this.contents.ParseFrom(this, rst); err != nil {
		return nil, err
	}
	return this.contents, nil
}
func (this *Page) GetRotate() int {
	rst := this.GetInheritableEntryValue("/Rotate")
	if rst == nil {
		return 0
	}
	return rst.(*basicobject.Integer).ValueInt()
}
func (this *Page) GetInheritableEntryValue(key string) basicobject.BasicObject {
	v := this.dic.Get(key)
	if v == nil {
		return this.Parent.GetInheritableEntryValue(key)
	}
	return v
}
func (this *Page) parseRequiredMediaBox() error {
	mb := this.GetInheritableEntryValue("/MediaBox")
	if mb == nil {
		return errors.Errorf("page(%v %v)无/MediaBox", this.ObjectNumber, this.ObjectVersionNumber)
	}
	this.MediaBox = new(data.Rectangle)
	if err := this.MediaBox.ParseFrom(mb.(*basicobject.Array)); err != nil {
		return err
	}
	return nil
}
func (this *Page) parseRequiredResources() error {
	this.Resources = new(Resources)
	value := this.GetInheritableEntryValue("/Resources")
	if err := this.Resources.ParseFrom(value, this.locator); err != nil {
		return errors.Wrapf(err, "Resources.ParseFrom")

	}
	return nil
}
